package com.zhangmeng.tools.controller;


import cn.hutool.crypto.digest.DigestUtil;
import com.zhangmeng.tools.dto.BucketFile;
import com.zhangmeng.tools.utils.*;
import io.minio.messages.Bucket;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.text.Text;
import javafx.stage.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 大文件上传
 *
 * @author zhangmeng
 * @version 1.0
 * @date 2023年9月15日15:19:58
 */
@Slf4j
public class MinioUploadController {

    @FXML
    public TextField endpoint;

    @FXML
    public TextField accessKey;

    @FXML
    public TextField secretKey;

    @FXML
    public ImageView iv;

    @FXML
    public Button file_choose;

    @FXML
    public Button upload;

    @FXML
    public TextField file_path;

    @FXML
    public ComboBox<String> backet_list;

    private final ObservableList<String> backet_item_list = FXCollections.observableArrayList();
    private final ObservableList<BucketFile> list = FXCollections.observableArrayList();

    @FXML
    public TableView<BucketFile> tableview;

    @FXML
    public TableColumn<BucketFile,String> file_name;

    @FXML
    public TableColumn<BucketFile,Number> file_size;

    @FXML
    public TableColumn<BucketFile,String> file_url;

    @FXML
    public TableColumn<BucketFile,String> file_bucket;

    @FXML
    public Button reload_config;

    @FXML
    public Button delete_bucket;

    @FXML
    public Button create_bucket;

    @FXML
    public TextField create_bucket_name;

    @FXML
    public Button load_init_config;

    public void reload(String bucketName){
        if (bucketName == null){
            return;
        }
        List<BucketFile> bucketFiles = MinioUtils.getFileList(bucketName);
        if (bucketFiles.size()>0){
            list.clear();
            list.addAll(bucketFiles);
        }
    }
    public void reload(){
        list.clear();
    }


    public void init_bucket_list(){
        backet_item_list.clear();
        //获取所有储存桶
        MinioUtils.getDefault();
        List<Bucket> buckets = MinioUtils.getAllBuckets();
        if (buckets.size()>0){
            for (Bucket bucket : buckets) {
                backet_item_list.add(bucket.name());
            }
        }

    }

    public void init_minio_config(){

        MinioUtils.objectMap.put("endpoint",endpoint.getText());
        MinioUtils.objectMap.put("accessKey",accessKey.getText());
        MinioUtils.objectMap.put("secretKey",secretKey.getText());
    }

    public void reload_minio_config(){
        MinioUtils.objectMap.put("endpoint",endpoint.getText());
        MinioUtils.objectMap.put("accessKey",accessKey.getText());
        MinioUtils.objectMap.put("secretKey",secretKey.getText());
        MinioUtils.reload();
        AlertUtils.alert_msg("重新加载成功!");
    }

    public void load_init(){
        init_minio_config();
        init_bucket_list();
    }

    @FXML
    public void initialize() {

        this.backet_list.setItems(backet_item_list);
        backet_list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                if (newValue != null){
                    reload(newValue);
                }
            }
        });

        //默认值
        endpoint.setText("http://192.168.1.254:9000");
        accessKey.setText("minioadmin");
        secretKey.setText("minioadmin");

        load_init_config.setOnAction(event -> {
            load_init();
        });
        tableview.setItems(list);
        file_name.setCellValueFactory(new PropertyValueFactory<BucketFile,String>("fileName"));
        file_size.setCellValueFactory(new PropertyValueFactory<BucketFile,Number>("size"));
        file_url.setCellValueFactory(new PropertyValueFactory<BucketFile,String>("url"));
        file_bucket.setCellValueFactory(new PropertyValueFactory<BucketFile,String>("bucketName"));

        file_name.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));
        file_size.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));
        file_url.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));
        file_bucket.prefWidthProperty().bind(tableview.widthProperty().divide(tableview.getColumns().size()));

        // 创建上下文菜单
        final ContextMenu contextMenu = new ContextMenu();
        MenuItem cat = new MenuItem("查看");
        MenuItem copy_url = new MenuItem("复制url");
        MenuItem menuItem = new MenuItem("删除");
        menuItem.setOnAction(event -> {
            list.remove(tableview.getSelectionModel().getSelectedItem());
        });
        contextMenu.getItems().add(cat);
        cat.setOnAction(event -> {
            BucketFile selectedItem = tableview.getSelectionModel().getSelectedItem();
            iv.setImage(new Image(selectedItem.getUrl()));
        });
        contextMenu.getItems().add(copy_url);
        copy_url.setOnAction(event -> {
            ClipboardUtils.setString(tableview.getSelectionModel().getSelectedItem().getUrl());
        });

        contextMenu.getItems().add(menuItem);
        // 添加事件监听器来处理上下文菜单的显示
        tableview.setOnContextMenuRequested(event -> {
            // 只有当表格有选中项时才显示上下文菜单
            if (!tableview.getSelectionModel().isEmpty()) {
                contextMenu.show(tableview, event.getScreenX(), event.getScreenY());
            }
        });

        tableview.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<BucketFile>() {
            @Override
            public void changed(ObservableValue<? extends BucketFile> observable, BucketFile oldValue, BucketFile newValue) {
                if (newValue != null) {
                    System.out.println(newValue.getFileName());
                }
            }
        });

        file_choose.setText(null);
        ImageView iv = new ImageView(new Image(ImagePath.path(ImagePath.ImagePathType.IMAGE_FILE)));
        iv.setPreserveRatio(true);
        iv.setFitWidth(18);
        file_choose.setGraphic(iv);
        file_choose.setOnAction(event -> choose_file());

        upload.setOnAction(event -> {

            if (endpoint.getText().length() == 0) {
                AlertUtils.alert_warning("endpoint不能为空!");
                return;
            }

            if (accessKey.getText().length() == 0) {
                AlertUtils.alert_warning("accessKey不能为空!");
                return;
            }

            if (secretKey.getText().length() == 0) {
                AlertUtils.alert_warning("secretKey不能为空!");
                return;
            }

            if (backet_list.getSelectionModel().getSelectedItem() == null) {
                AlertUtils.alert_warning("请选择bucket再试!");
                return;
            }
            File file = new File(file_path.getText());
//            String extension = FilenameUtils.getExtension(file.getName());
//            if (extension.equals("jpg") || extension.equals("png")) {
//                images_upload();
//            }
//            if (extension.equals("mp4") || extension.equals("avi")) {
//                videos_upload();
//            }

            MinioUtils.upload_file(file,backet_list.getSelectionModel().getSelectedItem());
            reload(backet_list.getSelectionModel().getSelectedItem());
        });

        reload_config.setOnAction(event -> {
            reload_minio_config();
        });

        create_bucket.setOnAction(event -> {
            if (create_bucket_name.getText().length() == 0) {
                AlertUtils.alert_warning("bucket的名称不能为空!");
                return;
            }
            MinioUtils.createBucket(create_bucket_name.getText());
            init_bucket_list();
        });
        delete_bucket.setOnAction(event -> {

            // 用户点击了确定按钮
            if (backet_list.getSelectionModel().getSelectedItem() == null){
                MinioUtils.warning_msg("请选择将要删除的bucket在试!");
                return;
            }

            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.initModality(Modality.APPLICATION_MODAL);
            alert.setTitle("确认");
            alert.setHeaderText("你确定要继续吗？");
            alert.setContentText("这将执行一个操作。");
            Optional<ButtonType> result = alert.showAndWait();
            result.ifPresent(response -> {
                if (response == ButtonType.OK) {
                    //清空
                    List<BucketFile> fileList = MinioUtils.getFileList(backet_list.getSelectionModel().getSelectedItem());
                    List<String> del_list = fileList.stream().map(BucketFile::getFileName).collect(Collectors.toList());

                    MinioUtils.removeFiles(backet_list.getSelectionModel().getSelectedItem(), del_list);
                    MinioUtils.removeBucket(backet_list.getSelectionModel().getSelectedItem());
                    AlertUtils.alert_msg("删除成功!");
                    init_bucket_list();
                    reload();
                } else {
                }
            });
        });
    }

    public void videos_upload() {
        File file = new File(file_path.getText());
        MinioUtils.getInstance(endpoint.getText(), accessKey.getText(), secretKey.getText());
        try {
            MinioUtils.FileChunkReader filereader = new MinioUtils.FileChunkReader(file.toPath(), 1024 * 1024 * 10);
            byte[] chunk;
            int i = 0;
            while ((chunk = filereader.readNextChunk()) != null) {
                // process the chunk
                String fileMd5 = DigestUtil.md5Hex(chunk);
                //判断分块是否存在
                if (!MinioUtils.checkChunk(fileMd5, i, backet_list.getSelectionModel().getSelectedItem())) {
                    //得到分块文件的目录路径
                    String chunkFileFolderPath = MinioUtils.getChunkFileFolderPath(fileMd5);
                    //得到分块文件的路径
                    String chunkFilePath = chunkFileFolderPath + i;
                    try {
                        //将文件存储至minIO
                        MinioUtils.addMediaFilesToMinIO(chunk, backet_list.getSelectionModel().getSelectedItem(), chunkFilePath, "application/octet-stream");
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }

            //合并分块
            String fileExt = "";
            String mergeFilePath = MinioUtils.getFilePathByMd5(filereader.getMd5(),fileExt);

            try {
                //上传文件到minIO
                MinioUtils.addMediaFilesToMinIO(filereader.getFile().getAbsolutePath(), backet_list.getSelectionModel().getSelectedItem(), mergeFilePath);
                log.debug("合并文件上传MinIO完成{}", filereader.getFile().getAbsolutePath());
            } catch (Exception e) {
                e.printStackTrace();
                log.error("合并文件时上传文件出错");
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void images_upload() {
        File file = new File(file_path.getText());
        MinioUtils.getInstance(endpoint.getText(), accessKey.getText(), secretKey.getText());
        try {
            byte[] bytes = FileUtils.readFileToByteArray(file);
            String md5Hex = DigestUtil.md5Hex(bytes);
            String contentType = Files.probeContentType(file.toPath());
            String extension = FilenameUtils.getExtension(file.getName());
            MinioUtils.addMediaFilesToMinIO(bytes, backet_list.getSelectionModel().getSelectedItem(), md5Hex + "." + extension, contentType);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void choose_file() {
        Stage stage = (Stage) file_choose.getScene().getWindow();
        FileChooser dc = new FileChooser();
        dc.setTitle("文件选择");
        dc.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("图片类型", "*.jpg", "*.png"));
        File file = dc.showOpenDialog(stage);
        if (file != null) {
            String path = file.getAbsolutePath();
            file_path.setText(path);
            log.info("base64---file:{}", path);
            iv.setImage(new Image(file.getPath()));
        }
    }
}
